home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 359_11 / patch5.000 / EMU387_EMU.CC < prev    next >
C/C++ Source or Header  |  1991-09-11  |  7KB  |  288 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "emu.h"
  4. #include "const.h"
  5.  
  6. int modrm;
  7.  
  8. char saw[256*8];
  9.  
  10. int status_word = 0;
  11. int control_word = 0x77e;
  12. reg regs[8] = {
  13.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  14.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  15.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  16.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  17.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  18.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  19.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  20.  { SIGN_POS, TW_E, 0, 0x0, 0x0 },
  21. };
  22. int top = 0;
  23.  
  24. FUNC esc_table[64] = {
  25.   emu_00, emu_10, emu_20, emu_30, emu_40, emu_50, emu_60, emu_70,
  26.   emu_01, emu_11, emu_21, emu_31, emu_41, emu_51, emu_61, emu_71,
  27.   emu_02, emu_12, emu_22, emu_32, emu_42, emu_52, emu_62, emu_72,
  28.   emu_03, emu_13, emu_23, emu_33, emu_43, emu_53, emu_63, emu_73,
  29.   emu_04, emu_14, emu_24, emu_34, emu_44, emu_54, emu_64, emu_74,
  30.   emu_05, emu_15, emu_25, emu_35, emu_45, emu_55, emu_65, emu_75,
  31.   emu_06, emu_16, emu_26, emu_36, emu_46, emu_56, emu_66, emu_76,
  32.   emu_07, emu_17, emu_27, emu_37, emu_47, emu_57, emu_67, emu_77,
  33. };
  34.  
  35. int emu_initted = 0;
  36.  
  37. void emu_entry()
  38. {
  39.   if (emu_initted != 0x12345678)
  40.   {
  41.     emu_initted = 0x12345678;
  42. //    eprintf(
  43. //    "Installing the 80387 Emulator.  Copyright (C) 1991 DJ Delorie.\n"
  44. //    "WARNING: This is a TEST version of this emulator.  If it doesn't work,\n"
  45. //    "then don't use it.  Not all of the opcodes are implemented, and the\n"
  46. //    "ones that are may not work right in extreme cases.  Use at your own risk.\n"
  47. //    );
  48.   }
  49. //  eprintf("eax=0x%08x ebx=0x%08x ecx=0x%08x edx=0x%08x\n", eax, ebx, ecx, edx);
  50. //  eprintf("esi=0x%08x edi=0x%08x ebp=0x%08x eip=0x%08x\n", esi, edi, ebp, eip);
  51.   if (*eip == 0x66) // operand size - we know what size we need
  52.     eip++;
  53.   if (*eip == 0x9b) // fwait
  54.     return;
  55. //  int see = ((int)(eip[0] & 7) << 8) | eip[1];
  56. //  if (saw[see] != 42)
  57. //  {
  58. //    eprintf("EMU387: %02x %02x %02x %02x - e%d%d", eip[0], eip[1], eip[2], eip[3], eip[0]&7, (eip[1]>>3)&7);
  59. //    eprintf(" s%d\n", eip[1]&7);
  60. //    saw[see] = 42;
  61. //  }
  62.   int esc_value = *eip++ & 7;
  63.   modrm = *eip++;
  64.   esc_value |= (modrm & 070);
  65.   (esc_table[esc_value])();
  66. //  emu_printall();
  67. }
  68.  
  69. void emu_bad()
  70. {
  71.   eprintf("Unimplemented 80387 Opcode at eip=0x%08x : %02x", eip-2, eip[-2]);
  72.   if (eip[-1] > 0277)
  73.     eprintf(" %02x", eip[-1]);
  74.   else
  75.     eprintf(" /%d", (eip[-1]>>3)&7);
  76.   eprintf(" - e%d%d", eip[-2]&7, (eip[-1]>>3)&7);
  77.   if (eip[-1] > 0277)
  78.     eprintf(" s%d", eip[-1]&7);
  79.   eprintf("\n");
  80.   exception(EX_I);
  81. }
  82.  
  83. void emu_printall()
  84. {
  85.   static char *tag_desc[] = { "Valid", "Zero", "Special", "Empty" };
  86.   status_word = status_word & ~SW_TOP;
  87.   status_word += (top&7) * SW_TOPS;
  88.   eprintf("  SW: 0x%04x  top=%d cc=%d%d%d%d    ", status_word, top&7,
  89.     status_word & SW_C3?1:0, status_word & SW_C2?1:0,
  90.     status_word & SW_C1?1:0, status_word & SW_C0?1:0);
  91.   eprintf("CW: 0x%04x\n", control_word);
  92.   for (int i=0; i<8; i++)
  93.   {
  94.     reg *r = &st(i);
  95.     switch (r->tag)
  96.     {
  97.       case TW_E:
  98.         continue;
  99.         eprintf("st(%d)                                ", i);
  100.         break;
  101.       case TW_Z:
  102.         eprintf("st(%d) %c .0000 0000 0000 0000         ",
  103.                 i, r->sign ? '-' : '+');
  104.         break;
  105.       case TW_S:
  106.       case TW_V:
  107.         eprintf("st(%d) %c .%04x %04x %04x %04x e%+-6d ", i,
  108.           r->sign ? '-' : '+',
  109.           (long)(r->sigh >> 16),
  110.           (long)(r->sigh & 0xFFFF),
  111.           (long)(r->sigl >> 16),
  112.           (long)(r->sigl & 0xFFFF),
  113.           r->exp - EXP_BIAS + 1);
  114.     }
  115.     eprintf("%s\n", tag_desc[r->tag]);
  116.   }
  117.   fflush(stderr);
  118. }
  119.  
  120. static struct {
  121.   int type;
  122.   char *name;
  123. } ex_names[] = {
  124.   EX_SO, "stack overflow",
  125.   EX_SU, "stack underflow",
  126.   EX_P, "loss of precision",
  127.   EX_U, "underflow",
  128.   EX_O, "overflow",
  129.   EX_Z, "divide by zero",
  130.   EX_D, "denormalized operand",
  131.   EX_I, "invalid operation",
  132.   0,0
  133. };
  134.  
  135. void exception(int n)
  136. {
  137.   int i;
  138.   status_word |= n;
  139.   if (n == EX_SU)
  140.     status_word &= ~SW_C1;
  141.   for (i=0; ex_names[i].type; i++)
  142.     if (ex_names[i].type == n)
  143.       break;
  144.   if (ex_names[i].type)
  145.     eprintf("80387 Exception: %s!\n", ex_names[i].name);
  146.   else
  147.     eprintf("80387 Exception: 0x%04x!\n", n);
  148.   if (~control_word & n & CW_EXM)
  149.   {
  150.     emu_printall();
  151.     asm("movl $0x4cff,%eax");
  152.     asm("int $0x21");
  153.   }
  154. }
  155.  
  156. void setcc(int cc)
  157. {
  158.   status_word &= ~(SW_C0|SW_C1|SW_C2|SW_C3);
  159.   status_word |= cc & (SW_C0|SW_C1|SW_C2|SW_C3);
  160. }
  161.  
  162. int full()
  163. {
  164.   if (st(7).tag != TW_E)
  165.   {
  166.     exception(EX_SO);
  167.     top--;
  168.     r_mov(CONST_NAN, st(0));
  169.     return 1;
  170.   }
  171.   return 0;
  172. }
  173.  
  174. int empty(int i)
  175. {
  176.   if (st(i).tag == TW_E)
  177.   {
  178.     exception(EX_SU);
  179.     return 1;
  180.   }
  181.   return 0;
  182. }
  183.  
  184. static int sregval(int reg, int mod)
  185. {
  186.   switch (reg)
  187.   {
  188.     case 0: return eax;
  189.     case 1: return ecx;
  190.     case 2: return edx;
  191.     case 3: return ebx;
  192.     case 4: return (mod==-1) ? 0 : esp;
  193.     case 5: return mod ? ebp : 0; // data
  194.     case 6: return esi;
  195.     case 7: return edi;
  196.   }
  197. }
  198.  
  199. static int scale[] = { 1, 2, 4, 8 };
  200.  
  201. static int getsib()
  202. {
  203.   int mod = modrm >> 6;
  204.   int sib = *eip++;
  205.   int ss = sib>>6;
  206.   int index = (sib>>3) & 7;
  207.   int base = sib & 7;
  208.   int rv = sregval(base, mod) + sregval(index, -1) * scale[ss];
  209.   int rv2;
  210.   switch (mod)
  211.   {
  212.     case 1:
  213.       rv2 = *(signed char *)eip++;
  214.       rv += rv2;
  215.       break;
  216.     case 0:
  217.       if (base != 5)
  218.         break;
  219.     case 2:
  220.       ((unsigned char *)&rv2)[0] = *eip++;
  221.       ((unsigned char *)&rv2)[1] = *eip++;
  222.       ((unsigned char *)&rv2)[2] = *eip++;
  223.       ((unsigned char *)&rv2)[3] = *eip++;
  224.       rv += rv2;
  225.       break;
  226.   }
  227.   return rv;
  228. }
  229.  
  230. static int regval(int reg, int mod)
  231. {
  232.   switch (reg)
  233.   {
  234.     case 0: return eax;
  235.     case 1: return ecx;
  236.     case 2: return edx;
  237.     case 3: return ebx;
  238.     case 4: return getsib();
  239.     case 5: return mod ? ebp : 0; // data
  240.     case 6: return esi;
  241.     case 7: return edi;
  242.   }
  243. }
  244.  
  245. void *get_modrm()
  246. {
  247.   int mod = modrm>>6;
  248.   int rm = modrm & 7;
  249.   int rv;
  250.   switch (mod)
  251.   {
  252.     case 0:
  253.       if (rm == 5)
  254.       {
  255.         ((unsigned char *)&rv)[0] = *eip++;
  256.         ((unsigned char *)&rv)[1] = *eip++;
  257.         ((unsigned char *)&rv)[2] = *eip++;
  258.         ((unsigned char *)&rv)[3] = *eip++;
  259.       }
  260.       else
  261.         rv = regval(rm, mod);
  262.       break;
  263.     case 1:
  264.       if (rm != 4)
  265.         rv = (*(signed char *)eip++) + regval(rm, mod);
  266.       else
  267.         rv = regval(rm, mod);
  268.       break;
  269.     case 2:
  270.       if (rm != 4)
  271.       {
  272.         ((unsigned char *)&rv)[0] = *eip++;
  273.         ((unsigned char *)&rv)[1] = *eip++;
  274.         ((unsigned char *)&rv)[2] = *eip++;
  275.         ((unsigned char *)&rv)[3] = *eip++;
  276.         rv += regval(rm, mod);
  277.       }
  278.       else
  279.         rv = regval(rm, mod);
  280.       break;
  281.     case 3:
  282.       eprintf("Attempt to get address from mod = 3\n");
  283.       exit(1);
  284.   }
  285. //  eprintf("modrm returning 0x%x\n", rv);
  286.   return (void *)rv;
  287. }
  288.